const { redisUtils } = require('../config/redis')
const logger = require('../utils/logger')

// 限流配置
const rateLimitConfig = {
  // 全局限流：每15分钟100次请求
  global: {
    windowMs: 15 * 60 * 1000, // 15分钟
    maxRequests: 100,
    message: '请求过于频繁，请稍后重试'
  },
  
  // 登录限流：每小时5次
  login: {
    windowMs: 60 * 60 * 1000, // 1小时
    maxRequests: 5,
    message: '登录尝试次数过多，请1小时后重试'
  },
  
  // 短信限流：每分钟1次，每小时10次
  sms: {
    windowMs: 60 * 1000, // 1分钟
    maxRequests: 1,
    hourlyWindowMs: 60 * 60 * 1000, // 1小时
    hourlyMaxRequests: 10,
    message: '短信发送过于频繁，请稍后重试'
  },
  
  // 广告观看限流：每分钟2次
  ad: {
    windowMs: 60 * 1000, // 1分钟
    maxRequests: 2,
    message: '操作过于频繁，请稍后重试'
  }
}

// 创建限流中间件
function createRateLimiter(config) {
  return async (req, res, next) => {
    try {
      const key = `rate_limit:${req.ip}:${req.route?.path || req.path}`
      const now = Date.now()
      const windowStart = now - config.windowMs
      
      // 获取当前窗口内的请求次数
      const requests = await redisUtils.get(key) || []
      
      // 清理过期的请求记录
      const validRequests = requests.filter(timestamp => timestamp > windowStart)
      
      // 检查是否超过限制
      if (validRequests.length >= config.maxRequests) {
        logger.warn(`Rate limit exceeded for IP: ${req.ip}, path: ${req.path}`)
        
        return res.status(429).json({
          success: false,
          code: 1006,
          message: config.message,
          retryAfter: Math.ceil(config.windowMs / 1000)
        })
      }
      
      // 记录当前请求
      validRequests.push(now)
      await redisUtils.set(key, validRequests, Math.ceil(config.windowMs / 1000))
      
      next()
    } catch (error) {
      logger.error('Rate limiter error:', error)
      // 限流器出错时不阻塞请求
      next()
    }
  }
}

// 特殊路径的限流中间件
function createPathRateLimiter(path, config) {
  return async (req, res, next) => {
    if (!req.path.includes(path)) {
      return next()
    }
    
    return createRateLimiter(config)(req, res, next)
  }
}

// 基于用户的限流中间件
function createUserRateLimiter(config) {
  return async (req, res, next) => {
    try {
      const userId = req.user?.userId || req.ip
      const key = `rate_limit:user:${userId}:${req.route?.path || req.path}`
      const now = Date.now()
      const windowStart = now - config.windowMs
      
      // 获取当前窗口内的请求次数
      const requests = await redisUtils.get(key) || []
      
      // 清理过期的请求记录
      const validRequests = requests.filter(timestamp => timestamp > windowStart)
      
      // 检查是否超过限制
      if (validRequests.length >= config.maxRequests) {
        logger.warn(`User rate limit exceeded for user: ${userId}, path: ${req.path}`)
        
        return res.status(429).json({
          success: false,
          code: 1006,
          message: config.message,
          retryAfter: Math.ceil(config.windowMs / 1000)
        })
      }
      
      // 记录当前请求
      validRequests.push(now)
      await redisUtils.set(key, validRequests, Math.ceil(config.windowMs / 1000))
      
      next()
    } catch (error) {
      logger.error('User rate limiter error:', error)
      // 限流器出错时不阻塞请求
      next()
    }
  }
}

// 短信特殊限流（分钟级和小时级）
async function smsRateLimiter(req, res, next) {
  try {
    const phone = req.body.phone
    if (!phone) {
      return next()
    }
    
    const now = Date.now()
    const minuteKey = `rate_limit:sms:${phone}:minute`
    const hourKey = `rate_limit:sms:${phone}:hour`
    
    // 检查分钟级限制
    const minuteRequests = await redisUtils.get(minuteKey) || []
    const validMinuteRequests = minuteRequests.filter(
      timestamp => timestamp > now - rateLimitConfig.sms.windowMs
    )
    
    if (validMinuteRequests.length >= rateLimitConfig.sms.maxRequests) {
      return res.status(429).json({
        success: false,
        code: 1006,
        message: '短信发送过于频繁，请1分钟后重试',
        retryAfter: 60
      })
    }
    
    // 检查小时级限制
    const hourRequests = await redisUtils.get(hourKey) || []
    const validHourRequests = hourRequests.filter(
      timestamp => timestamp > now - rateLimitConfig.sms.hourlyWindowMs
    )
    
    if (validHourRequests.length >= rateLimitConfig.sms.hourlyMaxRequests) {
      return res.status(429).json({
        success: false,
        code: 1006,
        message: '短信发送次数已达小时上限，请稍后重试',
        retryAfter: 3600
      })
    }
    
    // 记录请求
    validMinuteRequests.push(now)
    validHourRequests.push(now)
    
    await redisUtils.set(minuteKey, validMinuteRequests, 60)
    await redisUtils.set(hourKey, validHourRequests, 3600)
    
    next()
  } catch (error) {
    logger.error('SMS rate limiter error:', error)
    next()
  }
}

// 导出中间件
module.exports = createRateLimiter(rateLimitConfig.global)
module.exports.createRateLimiter = createRateLimiter
module.exports.createPathRateLimiter = createPathRateLimiter
module.exports.createUserRateLimiter = createUserRateLimiter
module.exports.smsRateLimiter = smsRateLimiter
module.exports.rateLimitConfig = rateLimitConfig